package fm.yichenet.mongo.service.impl;

import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import fm.api.yunpian.SmsApi;
import fm.cache.ConfigCache;
import fm.dao.MongoBaseDao;
import fm.entityEnum.ActionTypeEnum;
import fm.exception.BizException;
import fm.mongo.MCondition;
import fm.mongo.MRel;
import fm.mongo.MongoTable;
import fm.yichenet.mongo.service.SmsService;
import fm.util.DateUtils;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Random;

/**
 * Created by CM on 17/5/7.
 */
@Service
public class SmsServiceImpl implements SmsService {
    @Autowired
    MongoBaseDao mongoBaseDao;

    @Override
    public void sendSms(String phone, String content) throws Exception {
        SmsApi.sendSms(phone, content);
        log(phone, content, ActionTypeEnum.NORMAL);
    }

    @Override
    public void businessSmsSend(String phone, String actionType) throws Exception {
        String code = getCode();
        String content;

        switch (ActionTypeEnum.valueOf(actionType)) {
            case LOGIN_VERIFY:
                if (checkBussiness(phone, ActionTypeEnum.valueOf(actionType)) == true) {
                    throw new BizException("一小时内" + ActionTypeEnum.valueOf(actionType).getDesc() + "最多只能获取十次登陆验证码!");
                }
                content = "【" + ConfigCache.getConfig("YUNPIAN_SIGN") + "】您的登录验证码是" + code + ",有效时间为30分钟。";
                SmsApi.sendSms(phone, content);
                break;
            case REGISTER_VERIFY:
                if (checkBussiness(phone, ActionTypeEnum.valueOf(actionType)) == true) {
                    throw new BizException("一小时内" + ActionTypeEnum.valueOf(actionType).getDesc() + "最多只能获取十次注册验证码!");
                }
                content = "【" + ConfigCache.getConfig("YUNPIAN_SIGN") + "】您的注册验证码是" + code + ",有效时间为30分钟";
                SmsApi.sendSms(phone, content);
                break;
            case NORMAL:
                if (checkBussiness(phone, ActionTypeEnum.valueOf(actionType)) == true) {
                    throw new BizException("一小时内" + ActionTypeEnum.valueOf(actionType).getDesc() + "只能获取十次!");
                }
                break;
            case TRADE_ORDER:
                content = "【" + ConfigCache.getConfig("YUNPIAN_SIGN") + "】有新的订单，请即时登录衣车网App或管理平台进行处理。";
                sendSms(phone, content);
                break;
            case TEC_SERVICE_ORDER:
                content = "【" + ConfigCache.getConfig("YUNPIAN_SIGN") + "】收到一条维修订单，请即时登录衣车网App查看。";
                sendSms(phone, content);
                break;
            case ORDER_POSTS:
                content = "【" + ConfigCache.getConfig("YUNPIAN_SIGN") + "】您有订单发货啦，快上APP或者公众号查看一下吧。";
                sendSms(phone, content);
            default:
                throw new UnsupportedOperationException("未知的业务类型，无法发送短信");

        }
        log(phone, code, ActionTypeEnum.valueOf(actionType));

    }

    @Override
    public void checkAuthUserSms(String phone, String code) throws Exception {
        MCondition mc = MCondition.create(MRel.and);
        mc.append("phone", phone);
        mc.append("type", ActionTypeEnum.REGISTER_VERIFY.toString());
        mc.append("check_status", 0);
        mc.append(MCondition.create(MRel.lte).append("latm", new Date()));
        mc.append(MCondition.create(MRel.gte).append("latm", DateUtils.addMinute(new Date(), -30)));
        List<DBObject> items = (List<DBObject>) mongoBaseDao.getPageList(mc.toDBObject().toMap(), DBObject.class, 1, 1, MongoTable.sms_log, new BasicDBObject("latm", Sort.Direction.DESC.toString()));
        if (CollectionUtils.isEmpty(items)) {
            throw new BizException("短信验证码无效");
        }
        boolean result = String.valueOf(items.get(0).get("content")).equals(code);
        if (result == true) {
            mongoBaseDao.updateOne(mc.toDBObject().toMap(), new BasicDBObject("check_status", 1).toMap(), MongoTable.sms_log);
        } else {
            throw new BizException("验证码错误");
        }
    }


    /**
     * 短信发送记录
     *
     * @param phone   手机号码
     * @param content 内容
     * @param action  业务动作类型
     * @throws Exception
     */
    private void log(String phone, String content, ActionTypeEnum action) throws Exception {
        DBObject sendLog = new BasicDBObject("phone", phone);
        sendLog.put("content", content);
        sendLog.put("latm", new Date());
        sendLog.put("type", action);
        sendLog.put("typeDesc", action.getDesc());
        sendLog.put("check_status", 0);
        mongoBaseDao.insert(sendLog, MongoTable.sms_log);
    }

    /**
     * 校验同一个手机号码短信发送量，每个小时最多十条
     *
     * @param phone  手机号码
     * @param action 操作类型
     * @return
     * @throws Exception
     */
    private boolean checkBussiness(String phone, ActionTypeEnum action) throws Exception {
        MCondition mc = MCondition.create(MRel.and);
        mc.append("phone", phone);
        mc.append("type", action);
        mc.append(MCondition.create(MRel.gte).append("latm", DateUtils.addHour(new Date(), -1)));

        long count = mongoBaseDao.count(mc.toDBObject().toMap(), MongoTable.sms_log);
        return count > 10;
    }


    private String getCode() {
        Random random = new Random();
        String result = "";
        for (int i = 0; i < 6; i++) {
            result += random.nextInt(10);
        }
        return result;
    }
}
